package com.zjf.fupload.popup.actions;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import com.zjf.fupload.FUploadPlugin;
import com.zjf.fupload.entity.ServerInfo;
import com.zjf.fupload.ftp.FTPClientWrapper;
import com.zjf.fupload.ftp.FTPFileInfo;
import com.zjf.fupload.util.FileUtil;
  
/**
 * 选中服务器Dialog
 * @author zjf
 */
public class ChoosePathDialog extends Dialog {  
	
	private final DateFormat dformat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	private final static String back_tip = "上级目录";
  
    public ChoosePathDialog(Shell parentShell) {
		super(parentShell);
	}
  
    /**
	 * 服务器名称->服务器{@link ServerInfo}的映射
	 */
	private Map<String, ServerInfo> serverMap = new HashMap<String, ServerInfo>();
	
	private List<String> serverNames = new ArrayList<String>();
	
	private Table serverTable = null;
	private Table table = null;
	private Text uploadPathText = null;
	private FTPClientWrapper ftpClient;
	private FTPFileInfo[] infos = new FTPFileInfo[0];
	private ServerInfo confirmServerInfo = null;
    
    @Override
	protected Control createDialogArea(Composite parent) {
    	this.getShell().setText(FUploadPlugin.NAME);
    	serverMap.clear();
		serverNames.clear();
		String[] serverInfos = FUploadPlugin.getDefault().getServersPreference();
			//new String[] {"cc:ftp.cc.ac.cn:21:anonymous:123:/pub",
		//"唯品会:ftp.cc.ac.cn:21:anonymous:123:/pub/netlib"};
		final List<ServerInfo> serverList = new ArrayList<ServerInfo>();
		for(String serverInfo : serverInfos) {
			ServerInfo info = ServerInfo.parse(serverInfo);
			if(info != null) {
				serverMap.put(info.getName(), info);
				serverNames.add(info.getName());
				serverList.add(info);
			}
		}
		
    	Composite container = (Composite) super.createDialogArea(parent);
    	container.setLayout(new GridLayout(3, true));
    	
    	Composite serverComposite = new Composite(container, SWT.NONE);
    	GridLayout serverGridLayout = new GridLayout(1, false);  
    	serverComposite.setLayout(serverGridLayout);
    	
    	GridData sgriddata = new GridData(GridData.FILL_BOTH);
    	sgriddata.horizontalSpan = 1;
    	serverComposite.setLayoutData(sgriddata);
    	
    	String[] serverTableHeader = {"名称", "路径"};
    	String[][] serverRows = new String[serverList.size()][];
    	for(int i=0; i<serverRows.length; i++) {
    		ServerInfo info = serverList.get(i);
    		serverRows[i] = new String[] {info.getName(), info.getPath()};
    	}
    	
    	serverTable = createTable(serverComposite, serverTableHeader, serverRows);
        serverTable.addListener(SWT.MouseDown, new Listener() {  
            public void handleEvent(Event e) {  
            	TableItem item = serverTable.getItem( new Point(e.x, e.y));
            	if(item != null) {
            		final String serverName = item.getText(0).trim();
            		runFunction(new Function() {
						public void run() throws Exception {
	            			ServerInfo info = serverMap.get(serverName);
	            			newFtpClient(info);
		            		updateTableDatas();
						}
					});
            	}
            }  
        });  
        
		Composite composite = new Composite(container, SWT.NONE);  
		GridLayout gridLayout = new GridLayout(1, true); 
		composite.setLayout(gridLayout);  
		GridData griddata = new GridData(GridData.FILL_BOTH);
		griddata.horizontalSpan = 2;
		composite.setLayoutData(griddata);
		
		
		Composite pathComposite = new Composite(composite, SWT.NONE);
		GridLayout pathLayout = new GridLayout();  
		pathLayout.numColumns = 2;  
		pathLayout.horizontalSpacing = SWT.FILL;
		pathComposite.setLayout(pathLayout);
		GridData pathGD = new GridData(GridData.FILL_BOTH);
		pathComposite.setLayoutData(pathGD);
		
		Label label = new Label(pathComposite, SWT.NONE);
		label.setText("路径");
		URL imageURL = Platform.getBundle(FUploadPlugin.PROJECT_NAME).getEntry("icons/back.png");   
		Image image = ImageDescriptor.createFromURL(imageURL).createImage();
		label.setImage(image);
		label.addListener(SWT.MouseDown, new Listener() {
			public void handleEvent(Event e) {
				runFunction(new Function() {
					public void run() throws Exception {
						ftpClient.changeDirectoryUp();
	            		updateTableDatas();
					}
				});
			}
		});
		label.setToolTipText("点击到上级目录");
		
		uploadPathText = new Text(pathComposite, SWT.BORDER);
		GridData gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 1;
        uploadPathText.setText("");
        uploadPathText.setLayoutData(gridData);
		
		// 创建表头的字符串数组  
        String[] tableHeader = {"名称                     ", "更改日期            ", "大小(byte)", "类型"};  
        String[][] rows = new String[15][4];
        for(int i=0; i<rows.length; i++) {
        	rows[i] = new String[] {"", "", "", ""};
        }

        Composite tableComposite = new Composite(composite, SWT.NONE);
		GridLayout tableLayout = new GridLayout();  
		tableLayout.numColumns = 1;  
		tableLayout.horizontalSpacing = SWT.FILL;
		tableComposite.setLayout(pathLayout);
		GridData tableGD = new GridData(GridData.FILL_BOTH);
		tableComposite.setLayoutData(tableGD);
        table = createTable(tableComposite, tableHeader, rows);
        table.addMouseListener(new RightMenuListener(this));  
        table.addListener(SWT.MouseDoubleClick, new Listener() {  
            public void handleEvent(Event e) {  
            	TableItem item = table.getItem( new Point(e.x, e.y));
            	if(item != null) {
            		
            		final String dirName = item.getText(0).trim();
            		final String type = item.getText(3).trim();
            		ChoosePathDialog.this.runFunction(new Function() {
						public void run() throws Exception {
							boolean shouldUpdate = false;
		            		if(String.valueOf(FTPFileInfo.TYPE_DIRECTORY).equals(type)) {
			            		ftpClient.changeDirectory(dirName);
			            		shouldUpdate = true;
		            		} else if(String.valueOf(FTPFileInfo.TYPE_LINK).equals(type)) {
		            			for(FTPFileInfo info : infos) {
		            				if(info.getName().equals(dirName)) {
		            					ftpClient.changeDirectory(info.getLink());
		            					shouldUpdate = true;
		            					break;
		            				}
		            			}
		            		} else if(back_tip.equals(dirName)) {
		            			ftpClient.changeDirectoryUp();
		            			shouldUpdate = true;
		            		}
		            		if(shouldUpdate) {
		            			updateTableDatas();
		            		}
						}
					});
            	}
            }  
        });  
        
//        if(!serverList.isEmpty()) {
//        	
//        	runFunction(new Function() {
//				public void run() throws Exception {
//					newFtpClient(serverList.get(0));
//					updateTableDatas();
//				}
//			});
//        }
        
        uploadPathText.addKeyListener(new KeyListener() {
			@Override
			public void keyReleased(KeyEvent e) {
			}
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == 13) {  
					String path = uploadPathText.getText().trim();
					Pattern p = Pattern.compile("/?[^/]+(/[^/]+)*/?");
					Matcher m = p.matcher(path);
					if(!m.matches()) {
						MessageDialog.openInformation(ChoosePathDialog.this.getShell(), 
            					FUploadPlugin.NAME, "路径错误，请输入正确路径,如：/xx/xx/xxx");
						return;
					}
					
					if(!path.startsWith("/")) {
						path = "/" + path;
					}
					
					final String finalPath = path;
					
					runFunction(new Function() {
						public void run() throws Exception {
							ChoosePathDialog.this.ftpClient.changeDirectory(finalPath);
							ChoosePathDialog.this.updateTableDatas();
						}
					});
			    }  
			}
		});  
        
        uploadPathText.setFocus();
	        
    	return container;
    	
    }
    
    /**
	 * 保存选择的服务器，以便后续使用
	 */
	@Override
	protected void okPressed() {
		
		runFunction(new Function() {
			@Override
			public void run() throws Exception {
				if(ftpClient != null) {
		    		ftpClient.disconnect(true);
		    	}
			}
		});
		
		
		String serverName = serverTable.getItem(serverTable.getSelectionIndex()).getText(0);
		ServerInfo info = serverMap.get(serverName);
     	info.setPath(uploadPathText.getText().trim());
		this.confirmServerInfo = info;
		super.okPressed();
	}
    
    private void newFtpClient(ServerInfo info) throws Exception {
		FTPClientWrapper tmpFtpClient = new FTPClientWrapper(info.getServer(), 
				info.getPort(), info.getPath(), 
				info.getUsername(), info.getPassword());
		tmpFtpClient.login();
		
		FTPClientWrapper oldFTPClient = ftpClient;
		ftpClient = tmpFtpClient;
		if(oldFTPClient != null) {
			oldFTPClient.disconnect(true);
    	}
    }
    
    private void updateTableDatas() throws Exception {
    	String currentPath = ftpClient.currentDirectory();
    	uploadPathText.setText(currentPath);
    	
    	infos = ftpClient.list();
		String[][] datas = new String[infos.length + 1][4];
		datas[0] = new String[] {back_tip, " ", " ", " "};
		for(int i=0; i<infos.length; i++) {
			String date = "未知";
			if(infos[i].getModifiedDate() != null) {
				date = dformat.format(infos[i].getModifiedDate());
			}
			datas[i + 1] = new String[] { infos[i].getName(), date,
					String.valueOf(infos[i].getSize()), "" + infos[i].getType()};
		}
		updateTableDatas(table, datas);
    }
    
    protected void updateTableDatas(Table table, String[][] datas) {
		table.removeAll();
		for(int i=0; i < datas.length; i++) {
        	TableItem item = new TableItem(table, SWT.NONE);
        	String type = datas[i][3];
        	if(i == 0) {
        		URL imageURL = Platform.getBundle(FUploadPlugin.PROJECT_NAME).getEntry("icons/back.png");   
        		Image image = ImageDescriptor.createFromURL(imageURL).createImage();
        		item.setImage(0, image);
        	} else if(String.valueOf(FTPFileInfo.TYPE_DIRECTORY).equals(type)) {
        		URL imageURL = Platform.getBundle(FUploadPlugin.PROJECT_NAME).getEntry("icons/dir.png");   
        		Image image = ImageDescriptor.createFromURL(imageURL).createImage();
        		item.setImage(0, image);
        	} else {
        		URL imageURL = Platform.getBundle(FUploadPlugin.PROJECT_NAME).getEntry("icons/file.png");   
        		Image image = ImageDescriptor.createFromURL(imageURL).createImage();
        		
        		String fileName = datas[i][0];
        		String extension = FileUtil.getExtension(fileName);
        		if(!"".equals(extension)) {
        			Program p = Program.findProgram("." + extension);
        			if(p != null) {
        				ImageData data = p.getImageData();
        				image = new Image(table.getDisplay(), data);
        			}
        		}
        		
        		item.setImage(0, image);
        	}
            item.setText(datas[i]);  
        }
		
		table.redraw();
		
	}

	@Override
	protected Point getInitialSize(){
        return new Point(600, 520);//宽 高
    }
  
    // 创建表格  
    private Table createTable(Composite parent, String[] header, String[][] rows) {  
        // 表格布局  
        GridData gridData = new GridData();  
        gridData.horizontalAlignment = SWT.FILL;  
        gridData.grabExcessHorizontalSpace = true;  
        gridData.grabExcessVerticalSpace = true;  
        gridData.verticalAlignment = SWT.FILL;  
        gridData.verticalIndent = 2;
  
        // 创建表格，使用SWT.FULL_SELECTION样式，可选中一行  
        Table table = new Table(parent, SWT.BORDER | SWT.FULL_SELECTION);  
        table.setHeaderVisible(true);// 设置显示表头  
        table.setLayoutData(gridData);// 设置表格布局  
        table.setLinesVisible(true);// 设置显示表格线/*  
        
        for (int i = 0; i < header.length; i++) {  
            TableColumn tableColumn = new TableColumn(table, SWT.NONE);  
            tableColumn.setText(header[i]);  
            // 设置表头可移动，默认为false  
            tableColumn.setMoveable(true);  
        }  
        
        for(int i=0; i < rows.length; i++) {
        	TableItem item = new TableItem(table, SWT.NONE);
            item.setText(rows[i]);  
        }
       
        for (int i = 0; i < header.length; i++) {  
            table.getColumn(i).pack();  
        }  
        
        return table;
        
    }  
    
    public ServerInfo getConfirmServerInfo() {
		return confirmServerInfo;
	}
    
    protected Table getTable() {
    	return this.table;
    }
    
    protected FTPClientWrapper getFTPClient() {
    	return this.ftpClient;
    }

	protected void runFunction(Function f) {
		try {
			f.run();
		} catch (Exception expt) {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			PrintStream print = new PrintStream(out);
			expt.printStackTrace(print);
			MessageDialog.openError(ChoosePathDialog.this.getShell(), 
					FUploadPlugin.NAME, "发生错误：" + out.toString());
		}
	}
	
	interface Function {
		void run() throws Exception;
	}
  
}  